package org.ocean.general.sample.helper;

import org.ocean.general.sample.constant.OptionalConstant;
import org.ocean.general.sample.domain.entity.AutoDomain;
import org.ocean.general.sample.page.PageInfo;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class ScriptProviderHelper {

    /**
     * 参数填充
     * @param filed
     * @return
     */
    public static String parameterPadding(String filed){
        StringBuilder contentPadding = new StringBuilder();
        contentPadding.append(OptionalConstant.HASHTAG);
        contentPadding.append(OptionalConstant.LEFT_BIG_BRACKETS);
        contentPadding.append(filed);
        contentPadding.append(OptionalConstant.RIGHT_BIG_BRACKETS);
        return contentPadding.toString();
    }
    /**
     * 构建Conditional表达式脚本
     * @return
     */
    public static String buildConditionalScript(){
        StringBuilder whereBuilder = new StringBuilder();
        whereBuilder.append(OptionalConstant.SPACE).append(OptionalConstant.LABEL_START_IF).append(OptionalConstant.SPACE);
        whereBuilder.append("test=\"conditional != null and conditional.builder!=null and conditional.builder != '' \"");
        whereBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        whereBuilder.append(OptionalConstant.LABEL_START_WHERE);

        //查询条件Script
        whereBuilder.append(OptionalConstant.LABEL_START_IF).append(OptionalConstant.SPACE);
        whereBuilder.append("test=\"conditional.builder.sqls != null and conditional.builder.sqls.sqls.size()>0 \"");
        whereBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);

        whereBuilder.append(OptionalConstant.LABEL_START_FOREACH).append(OptionalConstant.SPACE);
        whereBuilder.append("collection=\"conditional.builder.sqls.sqls\" item=\"sql\"");
        whereBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        whereBuilder.append(buildChoseScript());
        whereBuilder.append(OptionalConstant.LABEL_END_FOREACH);

        whereBuilder.append(OptionalConstant.LABEL_END_IF);

        whereBuilder.append(OptionalConstant.LABEL_END_WHERE);

        //排序Script
        whereBuilder.append(OptionalConstant.LABEL_START_IF).append(OptionalConstant.SPACE);
        whereBuilder.append("test=\"conditional.builder.sqls.creatorSort != null and conditional.builder.sqls.creatorSort.keys.size()>0 \"");
        whereBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);

        whereBuilder.append(OptionalConstant.SPACE).append(OptionalConstant.ORDER_BY).append(OptionalConstant.SPACE);

        whereBuilder.append(OptionalConstant.LABEL_START_FOREACH).append(OptionalConstant.SPACE);
        whereBuilder.append("collection=\"conditional.builder.sqls.creatorSort.keys\" item=\"key\"  separator=\",\" ");
        whereBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        whereBuilder.append(" #{key}");
        whereBuilder.append(OptionalConstant.LABEL_END_FOREACH).append(OptionalConstant.SPACE);;

        whereBuilder.append("${conditional.builder.sqls.creatorSort.condition.value}").append(OptionalConstant.SPACE);;

        whereBuilder.append(OptionalConstant.LABEL_END_IF);

        whereBuilder.append(OptionalConstant.LABEL_END_IF);
        return whereBuilder.toString();
    }

    private static String buildChoseScript(){
        StringBuilder choseBuilder = new StringBuilder();
        choseBuilder.append(OptionalConstant.LABEL_START_CHOOSE).append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);

        choseBuilder.append(OptionalConstant.LABEL_START_WHEN).append(OptionalConstant.SPACE);
        choseBuilder.append("test=\"sql.value != null and sql.crucialState =='BETWEEN' or  sql.crucialState == 'NOT BETWEEN' \"");
        choseBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        choseBuilder.append(" ${sql.condition} ${sql.key} ${sql.crucialState}");
        choseBuilder.append(OptionalConstant.LABEL_START_FOREACH).append(OptionalConstant.SPACE);
        choseBuilder.append("collection=\"sql.value\" item=\"betweenValue\" separator=\"AND\"");
        choseBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        choseBuilder.append(" #{betweenValue}");
        choseBuilder.append(OptionalConstant.LABEL_END_FOREACH);
        choseBuilder.append(OptionalConstant.LABEL_END_WHEN);

        choseBuilder.append(OptionalConstant.LABEL_START_WHEN).append(OptionalConstant.SPACE);
        choseBuilder.append("test=\"sql.value != null and sql.crucialState =='IN' or  sql.crucialState == 'NOT IN' \"");
        choseBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        choseBuilder.append(" ${sql.condition} ${sql.key} ${sql.crucialState}");
        choseBuilder.append(OptionalConstant.LABEL_START_FOREACH).append(OptionalConstant.SPACE);
        choseBuilder.append("collection=\"sql.value\" item=\"inValue\" open=\"(\" separator=\",\" close=\")\"");
        choseBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        choseBuilder.append(" #{inValue}");
        choseBuilder.append(OptionalConstant.LABEL_END_FOREACH);
        choseBuilder.append(OptionalConstant.LABEL_END_WHEN);

        choseBuilder.append(OptionalConstant.LABEL_START_WHEN).append(OptionalConstant.SPACE);
        choseBuilder.append("test=\"sql.value != null and sql.value.size()==1 \"");
        choseBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        choseBuilder.append(" ${sql.condition} ${sql.key} ${sql.crucialState}");
        choseBuilder.append(OptionalConstant.LABEL_START_FOREACH).append(OptionalConstant.SPACE);
        choseBuilder.append("collection=\"sql.value\" item=\"sqlValue\"");
        choseBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        choseBuilder.append(" #{sqlValue}");
        choseBuilder.append(OptionalConstant.LABEL_END_FOREACH);
        choseBuilder.append(OptionalConstant.LABEL_END_WHEN);

        choseBuilder.append(OptionalConstant.LABEL_END_CHOOSE);
        return choseBuilder.toString();
    }
    public static String buildWhereParameterPadding(String field){
        StringBuilder whereBuilder  = new StringBuilder();
        whereBuilder.append(BatisHelper.getTableField(field));
        whereBuilder.append(OptionalConstant.EQUAL);
        whereBuilder.append(parameterPadding(field));
        return whereBuilder.toString();
    }

    public static String selectCommonScript(Class<?> cla){
        StringBuilder selectBuilder = new StringBuilder(OptionalConstant.SELECT);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalProviderHelper.getFieldColumn(cla).stream().collect(Collectors.joining(OptionalConstant.CHINA_COMMA)));
        selectBuilder.append(OptionalConstant.SPACE).append(OptionalConstant.SELECT_FROM).append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalProviderHelper.buildTableName(cla));
        return selectBuilder.toString();
    }
    public static String selectCommonConditionalScript(Class<?> cla){
        StringBuilder selectBuilder = new StringBuilder();
        selectBuilder.append(selectCommonScript(cla));
        selectBuilder.append(buildConditionalScript());
        return selectBuilder.toString();
    }
    public static String singleSelectPrimaryKeyScript(Class<?> cla){
        StringBuilder selectBuilder = new StringBuilder();
        selectBuilder.append(selectCommonScript(cla));
        selectBuilder.append(OptionalConstant.SPACE).append(OptionalConstant.WHERE).append(OptionalConstant.SPACE);
        String primaryKey = OptionalProviderHelper.findPrimaryKey(cla);
        selectBuilder.append(BatisHelper.getTableField(primaryKey)).append(OptionalConstant.EQUAL).append(parameterPadding("key"));
        return selectBuilder.toString();
    }

    public static String singleSelectPrimaryMoreKeyScript(Class<?> cla){
        StringBuilder selectBuilder = new StringBuilder();
        selectBuilder.append(selectCommonScript(cla));
        selectBuilder.append(OptionalConstant.SPACE).append(OptionalConstant.WHERE).append(OptionalConstant.SPACE);
        String primaryKey = OptionalProviderHelper.findPrimaryKey(cla);
        selectBuilder.append(BatisHelper.getTableField(primaryKey)).append(OptionalConstant.SPACE).append(OptionalConstant.IN).append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.LABEL_START_FOREACH).append(OptionalConstant.SPACE);
        selectBuilder.append("collection=\"ids\" item=\"item\" open=\"(\" separator=\",\" close=\")\"");
        selectBuilder.append(OptionalConstant.LABEL_RIGHT_ANGEL_BRACKETS);
        selectBuilder.append(parameterPadding("item"));
        selectBuilder.append(OptionalConstant.LABEL_END_FOREACH);
        return selectBuilder.toString();
    }

    public static String singleSelectCountScript(Class<?> cla){
        StringBuilder selectBuilder = new StringBuilder(OptionalConstant.SELECT);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.COUNT_FUNCTION);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.SELECT_FROM);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.START_BRACKETS_PREFIX);
        selectBuilder.append(selectCommonConditionalScript(cla));
        selectBuilder.append(OptionalConstant.END_BRACKETS_SUFFIX);
        selectBuilder.append(OptionalConstant.TEMP_VARIABLE);
        return selectBuilder.toString();
    }

    public static String singlePureSelectCountScript(Class<?> cla){
        StringBuilder selectBuilder = new StringBuilder(OptionalConstant.SELECT);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.COUNT_FUNCTION);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.SELECT_FROM);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalProviderHelper.buildTableName(cla));
        return selectBuilder.toString();
    }
    public static String singleSelectCountByConditionalScript(Class<?> cla){
        StringBuilder selectBuilder = new StringBuilder();
        selectBuilder.append(singlePureSelectCountScript(cla));
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(buildConditionalScript());
        return selectBuilder.toString();
    }

    public static String singleSelectBetweenCountScript(Class<?> cla){
        StringBuilder selectBuilder = new StringBuilder(OptionalConstant.SELECT);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.COUNT_FUNCTION);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.SELECT_FROM);
        selectBuilder.append(OptionalConstant.SPACE);
        selectBuilder.append(OptionalConstant.START_BRACKETS_PREFIX);
        selectBuilder.append(selectCommonScript(cla));
        selectBuilder.append(OptionalConstant.END_BRACKETS_SUFFIX);
        selectBuilder.append(OptionalConstant.TEMP_VARIABLE);
        return selectBuilder.toString();
    }

    public static String listSelectPageScript(Class<?> cla){
        String pageSql = selectCommonConditionalScript(cla);
        StringBuilder pageBuilder = new StringBuilder();
        pageBuilder.append(pageSql);
        pageBuilder.append(OptionalConstant.LIMIT).append(OptionalConstant.SPACE);
        pageBuilder.append("#{pageInfo.startOffset} , #{pageInfo.endOffset}");
        return pageBuilder.toString();
    }

    public static String listSelectPageSpecifyScript(Class<?> cla){
        String pageSql = selectCommonConditionalScript(cla);
        StringBuilder pageBuilder = new StringBuilder();
        pageBuilder.append(pageSql);
        pageBuilder.append(OptionalConstant.LIMIT).append(OptionalConstant.SPACE);
        pageBuilder.append("#{pageInfo.endOffset}");
        return pageBuilder.toString();
    }

    public static String listSelectBetweenPageScript(Class<?> cla,String primaryKey){
        String pageSql = selectCommonScript(cla);
        StringBuilder pageBuilder = new StringBuilder();
        pageBuilder.append(pageSql);
        pageBuilder.append(OptionalConstant.SPACE).append(OptionalConstant.WHERE).append(OptionalConstant.SPACE);
        pageBuilder.append(BatisHelper.getTableField(primaryKey));
        pageBuilder.append(OptionalConstant.BETWEEN).append(OptionalConstant.SPACE);
        pageBuilder.append("#{pageInfo.startOffset}");
        pageBuilder.append(OptionalConstant.SPACE).append(OptionalConstant.AND).append(OptionalConstant.SPACE);
        pageBuilder.append("#{pageInfo.endOffset}");
        return pageBuilder.toString();
    }

    public static String buildPluginPageScript(PageInfo pageInfo){
        StringBuilder pageScriptBuilder = new StringBuilder();
        pageScriptBuilder.append(OptionalConstant.SPACE).append(OptionalConstant.LIMIT).append(OptionalConstant.SPACE);
        pageScriptBuilder.append(pageInfo.getStartOffset());
        pageScriptBuilder.append(OptionalConstant.CHINA_COMMA);
        pageScriptBuilder.append(pageInfo.getEndOffset());
        pageScriptBuilder.append(OptionalConstant.SEMICOLON);
        return pageScriptBuilder.toString();
    }
}
